#ifndef DATACONVERTER_H
#define DATACONVERTER_H
#include <QByteArray>
#include <QObject>
#include <cstring>
#include <iostream>

enum DataConvertType { BigEndian, LittleEndian };

class DataConverter : public QObject {
  Q_OBJECT
public:
  /**
   * @brief Construct a new Data Converter object
   *
   * Converter extract or export data from or to
   * QByteArray Stream, through a data frame by frame.
   *
   * @param header the header of data frame
   * @param len the length of user data pratition in a byte frame.
   */
  explicit DataConverter(
      const QByteArray &header, const size_t &len,
      const DataConvertType &type = DataConvertType::LittleEndian);
  DataConverter() = delete;
  DataConverter(const DataConverter &) = delete;
  DataConverter(DataConverter &&) = delete;

  template <typename T> T pop(const bool &reverse = false);
  /**
   * @brief if the number of bytes for storing data mismatch
   * the number of bytes using by this type in memory, can use
   * this function to indicate the number of bytes we need for
   * this pop()
   *
   * @tparam T data type
   * @param num need number of bytes
   * @param EndType
   * @return T
   */
  template <typename T> T pop(const int &num, const bool &reverse = false);

  void beginPush();
  void endPush();
  template <typename T> void push(const T &val);
  template <typename T> void push(const T &val, const int &num);

  /**
   * @brief remove current data frame.
   *
   * @note you must use has() to confirm if there is a frame.
   */
  void next();

  /**
   * @brief Check if there is a entire data frame.
   *
   * @return true move to the found data frame and remove the previous bytes.
   * @return false do nothing.
   */
  bool has() const;

  void clear();
  const QByteArray &buffer() const;

  DataConverter &operator<<(const QByteArray &data);

private:
  const QByteArray header;
  const size_t len;
  const DataConvertType type;

  // is the status updated?
  mutable bool isUpdate = false;

  // is write
  bool isWriting = false;

  mutable QByteArray buf;
  mutable QByteArray frame_buf;
};

#endif